1 module main;
2 
3 import dlangui;
4 import dlangui.dialogs.dialog;
5 import dlangui.dialogs.filedlg;
6 import dlangui.dialogs.msgbox;
7 import std.stdio;
8 import std.conv;
9 import std.utf;
10 import std.algorithm;
11 import std.path;
12 
13 
14 mixin APP_ENTRY_POINT;
15 
16 class TimerTest : HorizontalLayout {
17     ulong timerId;
18     TextWidget _counter;
19     int _value;
20     Button _start;
21     Button _stop;
22     override bool onTimer(ulong id) {
23         _value++;
24         _counter.text = to!dstring(_value);
25         return true;
26     }
27     this() {
28         addChild(new TextWidget(null, "Timer test."d));
29         _counter = new TextWidget(null, "0"d);
30         _counter.fontSize(32);
31         _start = new Button(null, "Start timer"d);
32         _stop = new Button(null, "Stop timer"d);
33         _stop.enabled = false;
34         _start.click = delegate(Widget src) {
35             _start.enabled = false;
36             _stop.enabled = true;
37             timerId = setTimer(1000);
38             return true;
39         };
40         _stop.click = delegate(Widget src) {
41             _start.enabled = true;
42             _stop.enabled = false;
43             cancelTimer(timerId);
44             return true;
45         };
46         addChild(_start);
47         addChild(_stop);
48         addChild(_counter);
49     }
50 }
51 
52 static if (BACKEND_GUI) {
53     class AnimatedDrawable : Drawable {
54         DrawableRef background;
55         this() {
56             background = drawableCache.get("tx_fabric.tiled");
57         }
58         void drawAnimatedRect(DrawBuf buf, uint p, Rect rc, int speedx, int speedy, int sz) {
59             int x = (p * speedx % rc.width);
60             int y = (p * speedy % rc.height);
61             if (x < 0)
62                 x += rc.width;
63             if (y < 0)
64                 y += rc.height;
65             uint a = 64 + ((p / 2) & 0x7F);
66             uint r = 128 + ((p / 7) & 0x7F);
67             uint g = 128 + ((p / 5) & 0x7F);
68             uint b = 128 + ((p / 3) & 0x7F);
69             uint color = (a << 24) | (r << 16) | (g << 8) | b;
70             buf.fillRect(Rect(rc.left + x, rc.top + y, rc.left + x + sz, rc.top + y + sz), color);
71         }
72         void drawAnimatedIcon(DrawBuf buf, uint p, Rect rc, int speedx, int speedy, string resourceId) {
73             int x = (p * speedx % rc.width);
74             int y = (p * speedy % rc.height);
75             if (x < 0)
76                 x += rc.width;
77             if (y < 0)
78                 y += rc.height;
79             DrawBufRef image = drawableCache.getImage(resourceId);
80             buf.drawImage(x, y, image.get);
81         }
82         override void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0) {
83             background.drawTo(buf, rc, state, cast(int)(animationProgress / 695430), cast(int)(animationProgress / 1500000));
84             drawAnimatedRect(buf, cast(uint)(animationProgress / 295430), rc, 2, 3, 100);
85             drawAnimatedRect(buf, cast(uint)(animationProgress / 312400) + 100, rc, 3, 2, 130);
86             drawAnimatedIcon(buf, cast(uint)(animationProgress / 212400) + 200, rc, -2, 1, "dlangui-logo1");
87             drawAnimatedRect(buf, cast(uint)(animationProgress / 512400) + 300, rc, 2, -2, 200);
88             drawAnimatedRect(buf, cast(uint)(animationProgress / 214230) + 800, rc, 1, 2, 390);
89             drawAnimatedIcon(buf, cast(uint)(animationProgress / 123320) + 900, rc, 1, 2, "cr3_logo");
90             drawAnimatedRect(buf, cast(uint)(animationProgress / 100000) + 100, rc, -1, -1, 120);
91         }
92         @property override int width() {
93             return 1;
94         }
95         @property override int height() {
96             return 1;
97         }
98         ulong animationProgress;
99         void animate(long interval) {
100             animationProgress += interval;
101         }
102 
103     }
104 }
105 
106 class TextEditorWidget : VerticalLayout {
107     EditBox _edit;
108     this(string ID) {
109         super(ID);
110         _edit = new EditBox("editor");
111         _edit.layoutWidth = FILL_PARENT;
112         _edit.layoutHeight = FILL_PARENT;
113         addChild(_edit);
114     }
115 }
116 
117 static if (BACKEND_GUI) {
118     class SampleAnimationWidget : VerticalLayout {
119         AnimatedDrawable drawable;
120         DrawableRef drawableRef;
121         this(string ID) {
122             super(ID);
123             drawable = new AnimatedDrawable();
124             drawableRef = drawable;
125             padding = Rect(20, 20, 20, 20);
126             addChild(new TextWidget(null, "This is TextWidget on top of animated background"d));
127             addChild(new EditLine(null, "This is EditLine on top of animated background"d));
128             addChild(new Button(null, "This is Button on top of animated background"d));
129             addChild(new VSpacer());
130         }
131 
132         /// background drawable
133         @property override DrawableRef backgroundDrawable() const {
134             return (cast(SampleAnimationWidget)this).drawableRef;
135         }
136 
137         /// returns true is widget is being animated - need to call animate() and redraw
138         @property override bool animating() { return true; }
139         /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
140         override void animate(long interval) {
141             drawable.animate(interval);
142             invalidate();
143         }
144     }
145 }
146 
147 Widget createEditorSettingsControl(EditWidgetBase editor) {
148     HorizontalLayout res = new HorizontalLayout("editor_options");
149     res.addChild((new CheckBox("wantTabs", "wantTabs"d)).checked(editor.wantTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.wantTabs = checked; return true;}));
150     res.addChild((new CheckBox("useSpacesForTabs", "useSpacesForTabs"d)).checked(editor.useSpacesForTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.useSpacesForTabs = checked; return true;}));
151     res.addChild((new CheckBox("readOnly", "readOnly"d)).checked(editor.readOnly).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.readOnly = checked; return true;}));
152     res.addChild((new CheckBox("showLineNumbers", "showLineNumbers"d)).checked(editor.showLineNumbers).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.showLineNumbers = checked; return true;}));
153     res.addChild((new CheckBox("fixedFont", "fixedFont"d)).checked(editor.fontFamily == FontFamily.MonoSpace).addOnCheckChangeListener(delegate(Widget, bool checked) {
154         if (checked)
155             editor.fontFamily(FontFamily.MonoSpace).fontFace("Courier New");
156         else
157             editor.fontFamily(FontFamily.SansSerif).fontFace("Arial");
158         return true;
159     }));
160     res.addChild((new CheckBox("tabSize", "Tab size 8"d)).checked(editor.tabSize == 8).addOnCheckChangeListener(delegate(Widget, bool checked) {
161         if (checked)
162             editor.tabSize(8);
163         else
164             editor.tabSize(4);
165         return true;
166     }));
167     return res;
168 }
169 
170 enum : int {
171     ACTION_FILE_OPEN = 5500,
172     ACTION_FILE_SAVE,
173     ACTION_FILE_CLOSE,
174     ACTION_FILE_EXIT,
175 }
176 
177 debug(SDLSettings) {
178     import dlangui.core.settings;
179     void testSDL(string fn) {
180         Log.d("Loading SDL from ", fn);
181         Setting s = new Setting();
182         if (s.load(fn)) {
183             Log.d("JSON:\n", s.toJSON(true));
184         } else {
185             Log.e("failed to read SDL from ", fn);
186         }
187     }
188     void testSDLSettings() {
189         testSDL(`C:\Users\vlopatin\AppData\Roaming\.dlangide\settings.json`);
190         testSDL("dub.json");
191         testSDL("test1.sdl");
192     }
193 }
194 
195 /// entry point for dlangui based application
196 extern (C) int UIAppMain(string[] args) {
197     embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
198     // select translation file - for english language
199     Platform.instance.uiLanguage = "en";
200     // load theme from file "theme_default.xml"
201     //~ Platform.instance.uiTheme = "theme_default";
202     //Platform.instance.uiTheme = "theme_dark";
203 
204     Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable | WindowFlag.ExpandSize, 800, 700);
205 
206     static if (true) {
207         VerticalLayout contentLayout = new VerticalLayout();
208 
209         TabWidget tabs = new TabWidget("TABS");
210         tabs.tabClose = delegate(string tabId) {
211             tabs.removeTab(tabId);
212         };
213 
214         //=========================================================================
215         // create main menu
216 
217         MenuItem mainMenuItems = new MenuItem();
218         MenuItem fileItem = new MenuItem(new Action(1, "MENU_FILE"c));
219         fileItem.add(new Action(ACTION_FILE_OPEN, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control));
220         fileItem.add(new Action(ACTION_FILE_SAVE, "MENU_FILE_SAVE"c, "document-save", KeyCode.KEY_S, KeyFlag.Control));
221         MenuItem openRecentItem = new MenuItem(new Action(13, "MENU_FILE_OPEN_RECENT", "document-open-recent"));
222         openRecentItem.add(new Action(100, "&1: File 1"d));
223         openRecentItem.add(new Action(101, "&2: File 2"d));
224         openRecentItem.add(new Action(102, "&3: File 3"d));
225         openRecentItem.add(new Action(103, "&4: File 4"d));
226         openRecentItem.add(new Action(104, "&5: File 5"d));
227         fileItem.add(openRecentItem);
228         fileItem.add(new Action(ACTION_FILE_EXIT, "MENU_FILE_EXIT"c, "document-close"c, KeyCode.KEY_X, KeyFlag.Alt));
229 
230         MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT"));
231         editItem.add(new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy", KeyCode.KEY_C, KeyFlag.Control));
232         editItem.add(new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste", KeyCode.KEY_V, KeyFlag.Control));
233         editItem.add(new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut", KeyCode.KEY_X, KeyFlag.Control));
234         editItem.add(new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
235         editItem.add(new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
236         editItem.add(new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent", KeyCode.TAB, 0));
237         editItem.add(new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Control));
238         editItem.add(new Action(20, "MENU_EDIT_PREFERENCES"));
239 
240         MenuItem editPopupItem = new MenuItem(null);
241         editPopupItem.add(new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy", KeyCode.KEY_C, KeyFlag.Control));
242         editPopupItem.add(new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste", KeyCode.KEY_V, KeyFlag.Control));
243         editPopupItem.add(new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut", KeyCode.KEY_X, KeyFlag.Control));
244         editPopupItem.add(new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
245         editPopupItem.add(new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
246         editPopupItem.add(new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent", KeyCode.TAB, 0));
247         editPopupItem.add(new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Control));
248 
249         MenuItem viewItem = new MenuItem(new Action(60, "MENU_VIEW"));
250         MenuItem langItem = new MenuItem(new Action(61, "MENU_VIEW_LANGUAGE"));
251         auto onLangChange = delegate (MenuItem item) {
252             if (!item.checked)
253                 return false;
254             if (item.id == 611) {
255                 // set interface language to english
256                 platform.instance.uiLanguage = "en";
257             } else if (item.id == 612) {
258                 // set interface language to russian
259                 platform.instance.uiLanguage = "ru";
260             }
261             return true;
262         };
263         MenuItem enLang = (new MenuItem(new Action(611, "MENU_VIEW_LANGUAGE_EN"))).type(MenuItemType.Radio).checked(true);
264         MenuItem ruLang = (new MenuItem(new Action(612, "MENU_VIEW_LANGUAGE_RU"))).type(MenuItemType.Radio);
265         enLang.menuItemClick = onLangChange;
266         ruLang.menuItemClick = onLangChange;
267         langItem.add(enLang);
268         langItem.add(ruLang);
269         viewItem.add(langItem);
270         MenuItem themeItem = new MenuItem(new Action(62, "MENU_VIEW_THEME"));
271         MenuItem theme1 = (new MenuItem(new Action(621, "MENU_VIEW_THEME_DEFAULT"))).type(MenuItemType.Radio).checked(true);
272         MenuItem theme2 = (new MenuItem(new Action(622, "MENU_VIEW_THEME_DARK"))).type(MenuItemType.Radio);
273         MenuItem theme3 = (new MenuItem(new Action(623, "MENU_VIEW_THEME_CUSTOM1"))).type(MenuItemType.Radio);
274         auto onThemeChange = delegate (MenuItem item) {
275             if (!item.checked)
276                 return false;
277             if (item.id == 621) {
278                 platform.instance.uiTheme = "theme_default";
279             } else if (item.id == 622) {
280                 platform.instance.uiTheme = "theme_dark";
281             } else if (item.id == 623) {
282                 platform.instance.uiTheme = "theme_custom1";
283             }
284             return true;
285         };
286         theme1.menuItemClick = onThemeChange;
287         theme2.menuItemClick = onThemeChange;
288         theme3.menuItemClick = onThemeChange;
289         themeItem.add(theme1);
290         themeItem.add(theme2);
291         themeItem.add(theme3);
292         viewItem.add(themeItem);
293 
294         MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
295         windowItem.add(new Action(30, "MENU_WINDOW_PREFERENCES"));
296         windowItem.add(new Action(31, UIString.fromId("MENU_WINDOW_MINIMIZE")));
297         windowItem.add(new Action(32, UIString.fromId("MENU_WINDOW_MAXIMIZE")));
298         windowItem.add(new Action(33, UIString.fromId("MENU_WINDOW_RESTORE")));
299         MenuItem helpItem = new MenuItem(new Action(4, "MENU_HELP"c));
300         helpItem.add(new Action(40, "MENU_HELP_VIEW_HELP"));
301         MenuItem aboutItem = new MenuItem(new Action(41, "MENU_HELP_ABOUT"));
302         helpItem.add(aboutItem);
303         mainMenuItems.add(fileItem);
304         mainMenuItems.add(editItem);
305         mainMenuItems.add(viewItem);
306         mainMenuItems.add(windowItem);
307         mainMenuItems.add(helpItem);
308         MainMenu mainMenu = new MainMenu(mainMenuItems);
309         contentLayout.addChild(mainMenu);
310         // to let main menu handle keyboard shortcuts
311         contentLayout.keyToAction = delegate(Widget source, uint keyCode, uint flags) {
312             return mainMenu.findKeyAction(keyCode, flags);
313         };
314         contentLayout.onAction = delegate(Widget source, const Action a) {
315             if (a.id == ACTION_FILE_EXIT) {
316                 window.close();
317                 return true;
318             } else if (a.id == 31) {
319                 window.minimizeWindow();
320                 return true;
321             } else if (a.id == 32) {
322                 window.maximizeWindow();
323                 return true;
324             } else if (a.id == 33) {
325                 window.restoreWindow();
326                 return true;
327             } else if (a.id == 41) {
328                 window.showMessageBox(UIString.fromRaw("About"d), UIString.fromRaw("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d));
329                 return true;
330             } else if (a.id == ACTION_FILE_OPEN) {
331                 UIString caption;
332                 caption = "Open Text File"d;
333                 FileDialog dlg = new FileDialog(caption, window, null);
334                 dlg.allowMultipleFiles = true;
335                 dlg.addFilter(FileFilterEntry(UIString("FILTER_ALL_FILES", "All files (*)"d), "*"));
336                 dlg.addFilter(FileFilterEntry(UIString("FILTER_TEXT_FILES", "Text files (*.txt)"d), "*.txt"));
337                 dlg.addFilter(FileFilterEntry(UIString("FILTER_SOURCE_FILES", "Source files"d), "*.d;*.dd;*.c;*.cc;*.cpp;*.h;*.hpp"));
338                 dlg.addFilter(FileFilterEntry(UIString("FILTER_EXECUTABLE_FILES", "Executable files"d), "*", true));
339                 //dlg.filterIndex = 2;
340                 dlg.dialogResult = delegate(Dialog dlg, const Action result) {
341                     if (result.id == ACTION_OPEN.id) {
342                         string[] filenames = (cast(FileDialog)dlg).filenames;
343                         foreach (filename; filenames) {
344                             if (filename.endsWith(".d") || filename.endsWith(".txt") || filename.endsWith(".cpp") || filename.endsWith(".h") || filename.endsWith(".c")
345                                 || filename.endsWith(".json") || filename.endsWith(".dd") || filename.endsWith(".ddoc") || filename.endsWith(".xml") || filename.endsWith(".html")
346                                 || filename.endsWith(".html") || filename.endsWith(".css") || filename.endsWith(".log") || filename.endsWith(".hpp")) {
347                                     // open source file in tab
348                                     int index = tabs.tabIndex(filename);
349                                     if (index >= 0) {
350                                         // file is already opened in tab
351                                         tabs.selectTab(index, true);
352                                     } else {
353                                         SourceEdit editor = new SourceEdit(filename);
354                                         if (editor.load(filename)) {
355                                             tabs.addTab(editor, toUTF32(baseName(filename)), null, true);
356                                             tabs.selectTab(filename);
357                                         } else {
358                                             destroy(editor);
359                                             window.showMessageBox(UIString.fromRaw("File open error"d), UIString.fromRaw("Cannot open file "d ~ toUTF32(filename)));
360                                         }
361                                     }
362                                 } else {
363                                     Log.d("FileDialog.onDialogResult: ", result, " param=", result.stringParam);
364                                     window.showMessageBox(UIString.fromRaw("FileOpen result"d), UIString.fromRaw("Filename: "d ~ toUTF32(filename)));
365                                 }
366                         }
367                     }
368 
369                 };
370                 dlg.show();
371                 return true;
372             }
373             //else
374             //return contentLayout.dispatchAction(a);
375             return false;
376         };
377         mainMenu.menuItemClick = delegate(MenuItem item) {
378             Log.d("mainMenu.onMenuItemListener", item.label);
379             const Action a = item.action;
380             if (a) {
381                 return contentLayout.dispatchAction(a);
382             }
383             return false;
384         };
385 
386         // ========= create tabs ===================
387 
388         tabs.tabChanged = delegate(string newTabId, string oldTabId) {
389             window.windowCaption = tabs.tab(newTabId).text.value ~ " - dlangui example 1"d;
390         };
391         tabs.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
392 
393         // most of controls example
394         {
395             LinearLayout controls = new VerticalLayout("controls");
396             controls.layoutHeight(FILL_PARENT);
397             controls.padding = Rect(12.pointsToPixels,12.pointsToPixels,12.pointsToPixels,12.pointsToPixels);
398 
399             HorizontalLayout line1 = new HorizontalLayout();
400             controls.addChild(line1);
401 
402             GroupBox gb = new GroupBox("checkboxes", "CheckBox"d);
403             gb.addChild(new CheckBox("cb1", "CheckBox 1"d));
404             gb.addChild(new CheckBox("cb2", "CheckBox 2"d).checked(true));
405             gb.addChild(new CheckBox("cb3", "CheckBox disabled"d).enabled(false));
406             gb.addChild(new CheckBox("cb4", "CheckBox disabled"d).checked(true).enabled(false));
407             line1.addChild(gb);
408 
409             GroupBox gb2 = new GroupBox("radiobuttons", "RadioButton"d);
410             gb2.addChild(new RadioButton("rb1", "RadioButton 1"d).checked(true));
411             gb2.addChild(new RadioButton("rb2", "RadioButton 2"d));
412             gb2.addChild(new RadioButton("rb3", "RadioButton disabled"d).enabled(false));
413             line1.addChild(gb2);
414 
415             VerticalLayout col1 = new VerticalLayout();
416             GroupBox gb3 = new GroupBox("textbuttons", "Button"d, Orientation.Horizontal);
417             gb3.addChild(new Button("tb1", "Button"d));
418             gb3.addChild(new Button("tb2", "Button disabled"d).enabled(false));
419             col1.addChild(gb3);
420             GroupBox gb4 = new GroupBox("imagetextbuttons", "ImageTextButton"d, Orientation.Horizontal);
421             gb4.addChild(new ImageTextButton("itb1", "document-open", "Enabled"d));
422             gb4.addChild(new ImageTextButton("itb2", "document-save", "Disabled"d).enabled(false));
423             col1.addChild(gb4);
424             GroupBox gbtext = new GroupBox("text", "TextWidget"d, Orientation.Horizontal);
425             gbtext.addChild(new TextWidget("t1", "Red text"d).fontSize(12.pointsToPixels).textColor(0xFF0000));
426             gbtext.addChild(new TextWidget("t2", "Italic text"d).fontSize(12.pointsToPixels).fontItalic(true));
427             col1.addChild(gbtext);
428             line1.addChild(col1);
429 
430             VerticalLayout col2 = new VerticalLayout();
431             GroupBox gb31 = new GroupBox("switches", "SwitchButton"d, Orientation.Vertical);
432             gb31.addChild(new SwitchButton("sb1"));
433             gb31.addChild(new SwitchButton("sb2").checked(true));
434             gb31.addChild(new SwitchButton("sb3").enabled(false));
435             gb31.addChild(new SwitchButton("sb4").enabled(false).checked(true));
436             col2.addChild(gb31);
437             line1.addChild(col2);
438 
439             VerticalLayout col3 = new VerticalLayout();
440             GroupBox gb32 = new GroupBox("switches", "ImageButton"d, Orientation.Vertical);
441             gb32.addChild(new ImageButton("ib1", "edit-copy"));
442             gb32.addChild(new ImageButton("ib3", "edit-paste").enabled(false));
443             col3.addChild(gb32);
444             GroupBox gb33 = new GroupBox("images", "ImageWidget"d, Orientation.Vertical);
445             gb33.addChild(new ImageWidget("cr3_logo", "cr3_logo"));
446             col3.addChild(gb33);
447             line1.addChild(col3);
448 
449 
450             HorizontalLayout line2 = new HorizontalLayout();
451             controls.addChild(line2);
452 
453             GroupBox gb5 = new GroupBox("scrollbar", "horizontal ScrollBar"d);
454             gb5.addChild(new ScrollBar("sb1", Orientation.Horizontal));
455             line2.addChild(gb5);
456             GroupBox gb6 = new GroupBox("slider", "horizontal SliderWidget"d);
457             gb6.addChild(new SliderWidget("sb2", Orientation.Horizontal));
458             line2.addChild(gb6);
459             GroupBox gb7 = new GroupBox("editline1", "EditLine"d);
460             gb7.addChild(new EditLine("ed1", "Some text"d).minWidth(120.pointsToPixels));
461             line2.addChild(gb7);
462             GroupBox gb8 = new GroupBox("editline2", "EditLine disabled"d);
463             gb8.addChild(new EditLine("ed2", "Some text"d).enabled(false).minWidth(120.pointsToPixels));
464             line2.addChild(gb8);
465 
466             HorizontalLayout line3 = new HorizontalLayout();
467             line3.layoutWidth(FILL_PARENT);
468             GroupBox gbeditbox = new GroupBox("editbox", "EditBox"d, Orientation.Horizontal);
469             gbeditbox.layoutWidth(FILL_PARENT);
470             EditBox ed1 = new EditBox("ed1", "Some text in EditBox\nOne more line\nYet another text line");
471             ed1.layoutHeight(FILL_PARENT);
472             gbeditbox.addChild(ed1);
473             line3.addChild(gbeditbox);
474             GroupBox gbtabs = new GroupBox(null, "TabWidget"d);
475             gbtabs.layoutWidth(FILL_PARENT);
476             TabWidget tabs1 = new TabWidget("tabs1");
477             tabs1.addTab(new TextWidget("tab1", "TextWidget on tab page\nTextWidgets can be\nMultiline"d).maxLines(3), "Tab 1"d);
478             tabs1.addTab(new ImageWidget("tab2", "dlangui-logo1"), "Tab 2"d);
479             tabs1.tabHost.backgroundColor = 0xE0E0E0;
480             tabs1.tabHost.padding = Rect(10.pointsToPixels, 10.pointsToPixels, 10.pointsToPixels, 10.pointsToPixels);
481             gbtabs.addChild(tabs1);
482             line3.addChild(gbtabs);
483             controls.addChild(line3);
484 
485             HorizontalLayout line4 = new HorizontalLayout();
486             line4.layoutWidth(FILL_PARENT);
487             line4.layoutHeight(FILL_PARENT);
488             GroupBox gbgrid = new GroupBox("grid", "StringGridWidget"d, Orientation.Horizontal);
489             StringGridWidget grid = new StringGridWidget("stringgrid");
490             grid.resize(12, 10);
491             gbgrid.layoutWidth(FILL_PARENT);
492             gbgrid.layoutHeight(FILL_PARENT);
493             grid.layoutWidth(FILL_PARENT);
494             grid.layoutHeight(FILL_PARENT);
495             foreach (index, month; ["January"d, "February"d, "March"d, "April"d, "May"d, "June"d, "July"d, "August"d, "September"d, "October"d, "November"d, "December"d])
496                 grid.setColTitle(cast(int)index, month);
497             for (int y = 0; y < 10; y++)
498                 grid.setRowTitle(y, to!dstring(y+1));
499             //grid.alignment = Align.Right;
500             grid.setColWidth(0, 30.pointsToPixels);
501             grid.autoFit();
502             import std.random;
503             import std..string;
504             for (int x = 0; x < 12; x++) {
505                 for (int y = 0; y < 10; y++) {
506                     int n = uniform(0, 10000);
507                     grid.setCellText(x, y, to!dstring("%.2f".format(n / 100.0)));
508                 }
509             }
510             //grid.autoFit();
511             gbgrid.addChild(grid);
512             line4.addChild(gbgrid);
513 
514             GroupBox gbtree = new GroupBox("tree", "TreeWidget"d, Orientation.Vertical);
515             auto tree = new TreeWidget("gbtree");
516             //tree.layoutWidth(WRAP_CONTENT).layoutHeight(FILL_PARENT);
517             tree.maxHeight(200.pointsToPixels);
518             TreeItem tree1 = tree.items.newChild("group1", "Group 1"d, "document-open");
519             tree1.newChild("g1_1", "Group 1 item 1"d);
520             tree1.newChild("g1_2", "Group 1 item 2"d);
521             tree1.newChild("g1_3", "Group 1 item 3"d);
522             TreeItem tree2 = tree.items.newChild("group2", "Group 2"d, "document-save");
523             tree2.newChild("g2_1", "Group 2 item 1"d, "edit-copy");
524             tree2.newChild("g2_2", "Group 2 item 2"d, "edit-cut");
525             tree2.newChild("g2_3", "Group 2 item 3"d, "edit-paste");
526             tree2.newChild("g2_4", "Group 2 item 4"d);
527             TreeItem tree3 = tree.items.newChild("group3", "Group 3"d);
528             tree3.newChild("g3_1", "Group 3 item 1"d);
529             tree3.newChild("g3_2", "Group 3 item 2"d);
530             TreeItem tree32 = tree3.newChild("g3_3", "Group 3 item 3"d);
531             tree3.newChild("g3_4", "Group 3 item 4"d);
532             tree32.newChild("group3_2_1", "Group 3 item 2 subitem 1"d);
533             tree32.newChild("group3_2_2", "Group 3 item 2 subitem 2"d);
534             tree32.newChild("group3_2_3", "Group 3 item 2 subitem 3"d);
535             tree32.newChild("group3_2_4", "Group 3 item 2 subitem 4"d);
536             tree32.newChild("group3_2_5", "Group 3 item 2 subitem 5"d);
537             tree3.newChild("g3_5", "Group 3 item 5"d);
538             tree3.newChild("g3_6", "Group 3 item 6"d);
539             gbtree.addChild(tree);
540             tree.items.selectItem(tree1);
541             // test adding new tree items
542             HorizontalLayout newTreeItem = new HorizontalLayout();
543             newTreeItem.layoutWidth = FILL_PARENT;
544             EditLine edNewTreeItem = new EditLine("newTreeItem", "new item"d);
545             edNewTreeItem.layoutWidth = FILL_PARENT;
546             Button btnAddItem = new Button("btnAddTreeItem", "Add"d);
547             Button btnRemoveItem = new Button("btnRemoveTreeItem", "Remove"d);
548             newTreeItem.addChild(edNewTreeItem);
549             newTreeItem.addChild(btnAddItem);
550             newTreeItem.addChild(btnRemoveItem);
551             btnAddItem.click = delegate(Widget source) {
552                 import std.random;
553                 dstring label = edNewTreeItem.text;
554                 string id = "item%d".format(uniform(1000000, 9999999, rndGen));
555                 TreeItem item = tree.items.selectedItem;
556                 if (item) {
557                     Log.d("Creating new tree item ", id, " ", label);
558                     TreeItem newItem = new TreeItem(id, label);
559                     item.addChild(newItem);
560                 }
561                 return true;
562             };
563             btnRemoveItem.click = delegate(Widget source) {
564                 TreeItem item = tree.items.selectedItem;
565                 if (item) {
566                     Log.d("Removing tree item ", item.id, " ", item.text);
567                     item.parent.removeChild(item);
568                 }
569                 return true;
570             };
571             gbtree.addChild(newTreeItem);
572             line4.addChild(gbtree);
573 
574             controls.addChild(line4);
575 
576             tabs.addTab(controls, "Controls"d);
577         }
578 
579         LinearLayout layout = new LinearLayout("tab1");
580 
581 
582         layout.addChild((new TextWidget()).textColor(0x00802000).text("Text widget 0"));
583         layout.addChild((new TextWidget()).textColor(0x40FF4000).text("Text widget"));
584         layout.addChild(new ProgressBarWidget().progress(300).animationInterval(50));
585         layout.addChild(new ProgressBarWidget().progress(-1).animationInterval(50));
586         layout.addChild((new Button("BTN1")).textResource("EXIT")); //.textColor(0x40FF4000)
587         layout.addChild(new TimerTest());
588 
589         static if (true) {
590 
591 
592         LinearLayout hlayout = new HorizontalLayout();
593         hlayout.layoutWidth(FILL_PARENT);
594         //hlayout.addChild((new Button()).text("<<")); //.textColor(0x40FF4000)
595         hlayout.addChild((new TextWidget()).text("Several").alignment(Align.Center));
596         hlayout.addChild((new ImageWidget()).drawableId("btn_radio").padding(Rect(5,5,5,5)).alignment(Align.Center));
597         hlayout.addChild((new TextWidget()).text("items").alignment(Align.Center));
598         hlayout.addChild((new ImageWidget()).drawableId("btn_check").padding(Rect(5,5,5,5)).alignment(Align.Center));
599         hlayout.addChild((new TextWidget()).text("in horizontal layout"));
600         hlayout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)).alignment(Align.Center));
601         hlayout.addChild((new EditLine("editline", "Some text to edit"d)).popupMenu(editPopupItem).alignment(Align.Center).layoutWidth(FILL_PARENT));
602         hlayout.addChild((new EditLine("passwd", "Password"d)).passwordChar('*').popupMenu(editPopupItem).alignment(Align.Center).layoutWidth(FILL_PARENT));
603         //hlayout.addChild((new Button()).text(">>")); //.textColor(0x40FF4000)
604         hlayout.backgroundColor = 0x8080C0;
605         layout.addChild(hlayout);
606 
607         LinearLayout vlayoutgroup = new HorizontalLayout();
608         LinearLayout vlayout = new VerticalLayout();
609         vlayout.addChild((new TextWidget()).text("VLayout line 1").textColor(0x40FF4000)); //
610         vlayout.addChild((new TextWidget()).text("VLayout line 2").textColor(0x40FF8000));
611         vlayout.addChild((new TextWidget()).text("VLayout line 2").textColor(0x40008000));
612         vlayout.addChild(new RadioButton("rb1", "Radio button 1"d));
613         vlayout.addChild(new RadioButton("rb2", "Radio button 2"d));
614         vlayout.addChild(new RadioButton("rb3", "Radio button 3"d));
615         vlayout.layoutWidth(FILL_PARENT);
616         vlayoutgroup.addChild(vlayout);
617         vlayoutgroup.layoutWidth(FILL_PARENT);
618         ScrollBar vsb = new ScrollBar("vscroll", Orientation.Vertical);
619         vlayoutgroup.addChild(vsb);
620         layout.addChild(vlayoutgroup);
621 
622         ScrollBar sb = new ScrollBar("hscroll", Orientation.Horizontal);
623         layout.addChild(sb.layoutHeight(WRAP_CONTENT).layoutWidth(FILL_PARENT));
624 
625         layout.addChild((new CheckBox("BTN2", "Some checkbox"d)));
626         layout.addChild((new TextWidget()).textColor(0x40FF4000).text("Text widget"));
627         layout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)));
628         layout.addChild((new TextWidget()).textColor(0xFF4000).text("Text widget2").padding(Rect(5,5,5,5)).margins(Rect(5,5,5,5)).backgroundColor(0xA0A0A0));
629         layout.addChild((new RadioButton("BTN3", "Some radio button"d)));
630         layout.addChild((new TextWidget(null, "Text widget3 with very long text"d)).textColor(0x004000));
631         layout.addChild(new VSpacer()); // vertical spacer to fill extra space
632 
633 
634         Widget w = parseML(q{
635             VerticalLayout {
636                 id: vlayout
637                 margins: Rect { left: 5; right: 3; top: 2; bottom: 4 }
638                 padding: Rect { 5, 4, 3, 2 } // same as Rect { left: 5; top: 4; right: 3; bottom: 2 }
639                 TextWidget {
640                     /* this widget can be accessed via id myLabel1
641                     e.g. w.childById!TextWidget("myLabel1")
642                     */
643                     id: myLabel1
644                     text: "Some text"; padding: 5
645                     enabled: false
646                 }
647                 TextWidget {
648                     id: myLabel2
649                     text: SOME_TEXT_RESOURCE_ID; margins: 5
650                     enabled: true
651                 }
652             }
653         });
654         Log.d("id=", w.id, " text=", w.text, " padding=", w.padding, " margins=", w.margins,
655               " lbl1.text=", w.childById!TextWidget("myLabel1").text,
656               " lbl1.enabled=", w.childById!TextWidget("myLabel1").enabled,
657               " lbl2.text=", w.childById!TextWidget("myLabel2").text
658               );
659         destroy(w);
660 
661         layout.childById("BTN1").click = delegate (Widget w) {
662             Log.d("onClick ", w.id);
663             //w.backgroundImageId = null;
664             //w.backgroundColor = 0xFF00FF;
665             w.textColor = 0xFF00FF;
666             w.styleId = STYLE_BUTTON_NOMARGINS;
667             return true;
668         };
669         layout.childById("BTN2").click = delegate (Widget w) { Log.d("onClick ", w.id); return true; };
670         layout.childById("BTN3").click = delegate (Widget w) { Log.d("onClick ", w.id); return true; };
671 
672         }
673 
674         layout.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
675 
676         tabs.addTab(layout, "Misc"d);
677 
678         static if (true) {
679             // two long lists
680             // left one is list with widgets as items
681             // right one is list with string list adapter
682             HorizontalLayout longLists = new HorizontalLayout("tab2");
683             longLists.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
684 
685             ListWidget list = new ListWidget("list1", Orientation.Vertical);
686             list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
687 
688             StringListAdapter stringList = new StringListAdapter();
689             WidgetListAdapter listAdapter = new WidgetListAdapter();
690             listAdapter.add((new TextWidget()).text("This is a list of widgets"d).styleId("LIST_ITEM"));
691             stringList.add("This is a list of strings from StringListAdapter"d);
692             stringList.add("If you type with your keyboard,"d);
693             stringList.add("then you can find the"d);
694             stringList.add("item in the list"d);
695             stringList.add("neat!"d);
696             for (int i = 1; i < 1000; i++) {
697                 dstring label = "List item "d ~ to!dstring(i);
698                 listAdapter.add((new TextWidget()).text("Widget list - "d ~ label).styleId("LIST_ITEM"));
699                 stringList.add("Simple string - "d ~ label);
700             }
701             list.ownAdapter = listAdapter;
702             listAdapter.resetItemState(0, State.Enabled);
703             listAdapter.resetItemState(5, State.Enabled);
704             listAdapter.resetItemState(7, State.Enabled);
705             listAdapter.resetItemState(12, State.Enabled);
706             assert(list.itemEnabled(5) == false);
707             assert(list.itemEnabled(6) == true);
708             list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
709             list.selectItem(0);
710 
711             longLists.addChild(list);
712 
713             ListWidget list2 = new StringListWidget("list2");
714             list2.ownAdapter = stringList;
715             list2.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
716             list2.selectItem(0);
717             longLists.addChild(list2);
718 
719             VerticalLayout itemedit = new VerticalLayout();
720             itemedit.addChild(new TextWidget(null, "New item text:"d));
721             EditLine itemtext = new EditLine(null, "Text for new item"d);
722             itemedit.addChild(itemtext);
723             Button btn = new Button(null, "Add item"d);
724             itemedit.addChild(btn);
725             longLists.addChild(itemedit);
726             btn.click = delegate(Widget src)
727             {
728                 stringList.add(itemtext.text);
729                 listAdapter.add((new TextWidget()).text(itemtext.text).styleId("LIST_ITEM"));
730                 return true;
731             };
732             tabs.addTab(longLists, "TAB_LONG_LIST"c);
733         }
734 
735         {
736             LinearLayout layout3 = new VerticalLayout("tab3");
737             // 3 types of buttons: Button, ImageButton, ImageTextButton
738             layout3.addChild(new TextWidget(null, "Buttons in HorizontalLayout"d));
739             WidgetGroup buttons1 = new HorizontalLayout();
740             buttons1.addChild(new TextWidget(null, "Button widgets: "d));
741             buttons1.addChild((new Button("btn1", "Button"d)).tooltipText("Tooltip text for button"d));
742             buttons1.addChild((new Button("btn2", "Disabled Button"d)).enabled(false));
743             buttons1.addChild(new TextWidget(null, "ImageButton widgets: "d));
744             buttons1.addChild(new ImageButton("btn3", "text-plain"));
745             buttons1.addChild(new TextWidget(null, "disabled: "d));
746             buttons1.addChild((new ImageButton("btn4", "folder")).enabled(false));
747             layout3.addChild(buttons1);
748 
749             WidgetGroup buttons10 = new HorizontalLayout();
750             buttons10.addChild(new TextWidget(null, "ImageTextButton widgets: "d));
751             buttons10.addChild(new ImageTextButton("btn5", "text-plain", "Enabled"d));
752             buttons10.addChild((new ImageTextButton("btn6", "folder", "Disabled"d)).enabled(false));
753             buttons10.addChild(new TextWidget(null, "SwitchButton widgets: "d));
754             buttons10.addChild((new SwitchButton("SW1")).checked(true));
755             buttons10.addChild((new SwitchButton("SW2")).checked(false));
756             buttons10.addChild((new SwitchButton("SW3")).checked(true).enabled(false));
757             buttons10.addChild((new SwitchButton("SW4")).checked(false).enabled(false));
758             layout3.addChild(buttons10);
759 
760             WidgetGroup buttons11 = new HorizontalLayout();
761             buttons11.addChild(new TextWidget(null, "Construct buttons by action (Button, ImageButton, ImageTextButton): "d));
762             Action FILE_OPEN_ACTION = new Action(ACTION_FILE_OPEN, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control);
763             buttons11.addChild(new Button(FILE_OPEN_ACTION));
764             buttons11.addChild(new ImageButton(FILE_OPEN_ACTION));
765             buttons11.addChild(new ImageTextButton(FILE_OPEN_ACTION));
766             layout3.addChild(buttons11);
767 
768             WidgetGroup buttons12 = new HorizontalLayout();
769             buttons12.addChild(new TextWidget(null, "The same in disabled state: "d));
770             buttons12.addChild((new Button(FILE_OPEN_ACTION)).enabled(false));
771             buttons12.addChild((new ImageButton(FILE_OPEN_ACTION)).enabled(false));
772             buttons12.addChild((new ImageTextButton(FILE_OPEN_ACTION)).enabled(false));
773             layout3.addChild(buttons12);
774 
775             layout3.addChild(new VSpacer());
776             layout3.addChild(new TextWidget(null, "CheckBoxes in HorizontalLayout"d));
777             WidgetGroup buttons2 = new HorizontalLayout();
778             buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
779             buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
780             //buttons2.addChild(new ResizerWidget());
781             buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
782             buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
783             layout3.addChild(buttons2);
784 
785             layout3.addChild(new VSpacer());
786             layout3.addChild(new TextWidget(null, "RadioButtons in HorizontalLayout"d));
787             WidgetGroup buttons3 = new HorizontalLayout();
788             buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
789             buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
790             buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
791             buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
792             layout3.addChild(buttons3);
793 
794             layout3.addChild(new VSpacer());
795             layout3.addChild(new TextWidget(null, "ImageButtons HorizontalLayout"d));
796             WidgetGroup buttons4 = new HorizontalLayout();
797             buttons4.addChild(new ImageButton("btn1", "fileclose"));
798             buttons4.addChild(new ImageButton("btn2", "fileopen"));
799             buttons4.addChild(new ImageButton("btn3", "exit"));
800             layout3.addChild(buttons4);
801 
802             layout3.addChild(new VSpacer());
803             layout3.addChild(new TextWidget(null, "In vertical layouts:"d));
804             HorizontalLayout hlayout2 = new HorizontalLayout();
805             hlayout2.layoutHeight(FILL_PARENT); //layoutWidth(FILL_PARENT).
806 
807             buttons1 = new VerticalLayout();
808             buttons1.addChild(new TextWidget(null, "Buttons"d));
809             buttons1.addChild(new Button("btn1", "Button 1"d));
810             buttons1.addChild(new Button("btn2", "Button 2"d));
811             buttons1.addChild((new Button("btn3", "Button 3 - disabled"d)).enabled(false));
812             buttons1.addChild(new Button("btn4", "Button 4"d));
813             hlayout2.addChild(buttons1);
814             hlayout2.addChild(new HSpacer());
815 
816             buttons2 = new VerticalLayout();
817             buttons2.addChild(new TextWidget(null, "CheckBoxes"d));
818             buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
819             buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
820             buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
821             buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
822             hlayout2.addChild(buttons2);
823             hlayout2.addChild(new HSpacer());
824 
825             buttons3 = new VerticalLayout();
826             buttons3.addChild(new TextWidget(null, "RadioButtons"d));
827             buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
828             buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
829             //buttons3.addChild(new ResizerWidget());
830             buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
831             buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
832             hlayout2.addChild(buttons3);
833             hlayout2.addChild(new HSpacer());
834 
835             buttons4 = new VerticalLayout();
836             buttons4.addChild(new TextWidget(null, "ImageButtons"d));
837             buttons4.addChild(new ImageButton("btn1", "fileclose"));
838             buttons4.addChild(new ImageButton("btn2", "fileopen"));
839             buttons4.addChild(new ImageButton("btn3", "exit"));
840             hlayout2.addChild(buttons4);
841             hlayout2.addChild(new HSpacer());
842 
843             WidgetGroup buttons5 = new VerticalLayout();
844             buttons5.addChild(new TextWidget(null, "ImageTextButtons"d));
845             buttons5.addChild(new ImageTextButton("btn1", "fileclose", "Close"d));
846             buttons5.addChild(new ImageTextButton("btn2", "fileopen", "Open"d));
847             buttons5.addChild(new ImageTextButton("btn3", "exit", "Exit"d));
848             hlayout2.addChild(buttons5);
849 
850 
851             layout3.addChild(hlayout2);
852 
853             layout3.addChild(new VSpacer());
854             layout3.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
855             tabs.addTab(layout3, "TAB_BUTTONS"c);
856         }
857 
858         TableLayout table = new TableLayout("TABLE");
859         table.colCount = 2;
860         // headers
861         table.addChild((new TextWidget(null, "Parameter Name"d)).alignment(Align.Right | Align.VCenter));
862         table.addChild((new TextWidget(null, "Edit Box to edit parameter"d)).alignment(Align.Left | Align.VCenter));
863         // row 1
864         table.addChild((new TextWidget(null, "Parameter 1 name"d)).alignment(Align.Right | Align.VCenter));
865         table.addChild((new EditLine("edit1", "Text 1"d)).layoutWidth(FILL_PARENT));
866         // row 2
867         table.addChild((new TextWidget(null, "Parameter 2 name bla bla"d)).alignment(Align.Right | Align.VCenter));
868         table.addChild((new EditLine("edit2", "Some text for parameter 2"d)).layoutWidth(FILL_PARENT));
869         // row 3
870         table.addChild((new TextWidget(null, "Param 3 is disabled"d)).alignment(Align.Right | Align.VCenter).enabled(false));
871         table.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT).enabled(false));
872         // normal readonly combo box
873         ComboBox combo1 = new ComboBox("combo1", ["item value 1"d, "item value 2"d, "item value 3"d, "item value 4"d, "item value 5"d, "item value 6"d]);
874         table.addChild((new TextWidget(null, "Combo box param"d)).alignment(Align.Right | Align.VCenter));
875         combo1.selectedItemIndex = 3;
876         table.addChild(combo1).layoutWidth(FILL_PARENT);
877         // disabled readonly combo box
878         ComboBox combo2 = new ComboBox("combo2", ["item value 1"d, "item value 2"d, "item value 3"d]);
879         table.addChild((new TextWidget(null, "Disabled combo box"d)).alignment(Align.Right | Align.VCenter));
880         combo2.enabled = false;
881         combo2.selectedItemIndex = 0;
882         table.addChild(combo2).layoutWidth(FILL_PARENT);
883 
884         table.margins(Rect(2,2,2,2)).layoutWidth(FILL_PARENT);
885         tabs.addTab(table, "TAB_TABLE_LAYOUT"c);
886 
887         //tabs.addTab((new TextWidget()).id("tab5").textColor(0x00802000).text("Tab 5 contents"), "Tab 5"d);
888 
889         //==========================================================================
890         // create Editors test tab
891         VerticalLayout editors = new VerticalLayout("editors");
892 
893         // EditLine sample
894         editors.addChild(new TextWidget(null, "EditLine: Single line editor"d));
895         EditLine editLine = new EditLine("editline1", "Single line editor sample text");
896         editors.addChild(createEditorSettingsControl(editLine));
897         editors.addChild(editLine);
898         editLine.popupMenu = editPopupItem;
899 
900         // EditBox sample
901         editors.addChild(new TextWidget(null, "SourceEdit: multiline editor, for source code editing"d));
902 
903         SourceEdit editBox = new SourceEdit("editbox1");
904         editBox.text = q{#!/usr/bin/env rdmd
905 // Computes average line length for standard input.
906 import std.stdio;
907 
908 void main()
909 {
910     ulong lines = 0;
911     double sumLength = 0;
912     foreach (line; stdin.byLine())
913     {
914         ++lines;
915         sumLength += line.length;
916     }
917     writeln("Average line length: ",
918             lines ? sumLength / lines : 0);
919 }
920         }d;
921         editors.addChild(createEditorSettingsControl(editBox));
922         editors.addChild(editBox);
923         editBox.popupMenu = editPopupItem;
924 
925         editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
926         SourceEdit editBox2 = new SourceEdit("editbox2");
927         editBox2.content = editBox.content; // view the same content as first editbox
928         editors.addChild(editBox2);
929         editors.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
930 
931         tabs.addTab(editors, "TAB_EDITORS"c);
932 
933         //==========================================================================
934 
935         VerticalLayout gridContent = new VerticalLayout("GRID_CONTENT");
936         gridContent.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
937         HorizontalLayout gridSettings = new HorizontalLayout();
938         StringGridWidget grid = new StringGridWidget("GRID1");
939 
940         gridSettings.addChild((new CheckBox("fullColumnOnLeft", "fullColumnOnLeft"d)).checked(grid.fullColumnOnLeft).tooltipText("Extends scroll area to show full column at left when scrolled to rightmost column"d).addOnCheckChangeListener(delegate(Widget, bool checked) { grid.fullColumnOnLeft = checked; return true;}));
941         gridSettings.addChild((new CheckBox("fullRowOnTop", "fullRowOnTop"d)).checked(grid.fullRowOnTop).tooltipText("Extends scroll area to show full row at top when scrolled to end row"d).addOnCheckChangeListener(delegate(Widget, bool checked) { grid.fullRowOnTop = checked; return true;}));
942         gridContent.addChild(gridSettings);
943 
944         grid.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
945         grid.showColHeaders = true;
946         grid.showRowHeaders = true;
947         grid.resize(30, 50);
948         grid.fixedCols = 3;
949         grid.fixedRows = 2;
950         //grid.rowSelect = true; // testing full row selection
951         grid.multiSelect = true;
952         grid.selectCell(4, 6, false);
953         // create sample grid content
954         for (int y = 0; y < grid.rows; y++) {
955             for (int x = 0; x < grid.cols; x++) {
956                 grid.setCellText(x, y, "cell("d ~ to!dstring(x + 1) ~ ","d ~ to!dstring(y + 1) ~ ")"d);
957             }
958             grid.setRowTitle(y, to!dstring(y + 1));
959         }
960         for (int x = 0; x < grid.cols; x++) {
961             int col = x + 1;
962             dstring res;
963             int n1 = col / 26;
964             int n2 = col % 26;
965             if (n1)
966                 res ~= n1 + 'A';
967             res ~= n2 + 'A';
968             grid.setColTitle(x, res);
969         }
970         grid.autoFit();
971         gridContent.addChild(grid);
972         tabs.addTab(gridContent, "Grid"d);
973 
974         //==========================================================================
975         // Scroll view example
976         ScrollWidget scroll = new ScrollWidget("SCROLL1");
977         scroll.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
978         WidgetGroup scrollContent = new VerticalLayout("CONTENT");
979         scrollContent.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
980 
981         TableLayout table2 = new TableLayout("TABLE2");
982         table2.colCount = 2;
983         // headers
984         table2.addChild((new TextWidget(null, "Parameter Name"d)).alignment(Align.Right | Align.VCenter));
985         table2.addChild((new TextWidget(null, "Edit Box to edit parameter"d)).alignment(Align.Left | Align.VCenter));
986         // row 1
987         table2.addChild((new TextWidget(null, "Parameter 1 name"d)).alignment(Align.Right | Align.VCenter));
988         table2.addChild((new EditLine("edit1", "Text 1"d)).layoutWidth(FILL_PARENT));
989         // row 2
990         table2.addChild((new TextWidget(null, "Parameter 2 name bla bla"d)).alignment(Align.Right | Align.VCenter));
991         table2.addChild((new EditLine("edit2", "Some text for parameter 2 blah blah blah"d)).layoutWidth(FILL_PARENT));
992         // row 3
993         table2.addChild((new TextWidget(null, "Param 3"d)).alignment(Align.Right | Align.VCenter));
994         table2.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT));
995         // row 4
996         table2.addChild((new TextWidget(null, "Param 4"d)).alignment(Align.Right | Align.VCenter));
997         table2.addChild((new EditLine("edit3", "Parameter 4 value shdjksdfh hsjdfas hdjkf hdjsfk ah"d)).layoutWidth(FILL_PARENT));
998         // row 5
999         table2.addChild((new TextWidget(null, "Param 5 - edit text here - blah blah blah"d)).alignment(Align.Right | Align.VCenter));
1000         table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT));
1001         // row 6
1002         table2.addChild((new TextWidget(null, "Param 6 - just to fill content widget (DISABLED)"d)).alignment(Align.Right | Align.VCenter).enabled(false));
1003         table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT).enabled(false));
1004         // row 7
1005         table2.addChild((new TextWidget(null, "Param 7 - just to fill content widget (DISABLED)"d)).alignment(Align.Right | Align.VCenter).enabled(false));
1006         table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT).enabled(false));
1007         // row 8
1008         table2.addChild((new TextWidget(null, "Param 8 - just to fill content widget"d)).alignment(Align.Right | Align.VCenter));
1009         table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT));
1010         table2.margins(Rect(10,10,10,10)).layoutWidth(FILL_PARENT);
1011         scrollContent.addChild(table2);
1012 
1013         scrollContent.addChild(new TextWidget(null, "Now - some buttons"d));
1014         scrollContent.addChild(new ImageTextButton("btn1", "fileclose", "Close"d));
1015         scrollContent.addChild(new ImageTextButton("btn2", "fileopen", "Open"d));
1016         scrollContent.addChild(new TextWidget(null, "And checkboxes"d));
1017         scrollContent.addChild(new CheckBox("btn1", "CheckBox 1"d));
1018         scrollContent.addChild(new CheckBox("btn2", "CheckBox 2"d));
1019 
1020         scroll.contentWidget = scrollContent;
1021         tabs.addTab(scroll, "Scroll"d);
1022         //==========================================================================
1023         // tree view example
1024         TreeWidget tree = new TreeWidget("TREE1");
1025         tree.layoutWidth(WRAP_CONTENT).layoutHeight(FILL_PARENT);
1026         TreeItem tree1 = tree.items.newChild("group1", "Group 1"d, "document-open");
1027         tree1.newChild("g1_1", "Group 1 item 1"d);
1028         tree1.newChild("g1_2", "Group 1 item 2"d);
1029         tree1.newChild("g1_3", "Group 1 item 3"d);
1030         TreeItem tree2 = tree.items.newChild("group2", "Group 2"d, "document-save");
1031         tree2.newChild("g2_1", "Group 2 item 1"d, "edit-copy");
1032         tree2.newChild("g2_2", "Group 2 item 2"d, "edit-cut");
1033         tree2.newChild("g2_3", "Group 2 item 3"d, "edit-paste");
1034         tree2.newChild("g2_4", "Group 2 item 4"d);
1035         TreeItem tree3 = tree.items.newChild("group3", "Group 3"d);
1036         tree3.newChild("g3_1", "Group 3 item 1"d);
1037         tree3.newChild("g3_2", "Group 3 item 2"d);
1038         TreeItem tree32 = tree3.newChild("g3_3", "Group 3 item 3"d);
1039         tree3.newChild("g3_4", "Group 3 item 4"d);
1040         tree32.newChild("group3_2_1", "Group 3 item 2 subitem 1"d);
1041         tree32.newChild("group3_2_2", "Group 3 item 2 subitem 2"d);
1042         tree32.newChild("group3_2_3", "Group 3 item 2 subitem 3"d);
1043         tree32.newChild("group3_2_4", "Group 3 item 2 subitem 4"d);
1044         tree32.newChild("group3_2_5", "Group 3 item 2 subitem 5"d);
1045         tree3.newChild("g3_5", "Group 3 item 5"d);
1046         tree3.newChild("g3_6", "Group 3 item 6"d);
1047 
1048         LinearLayout treeLayout = new HorizontalLayout("TREE");
1049         LinearLayout treeControlledPanel = new VerticalLayout();
1050         treeLayout.layoutWidth = FILL_PARENT;
1051         treeControlledPanel.layoutWidth = FILL_PARENT;
1052         treeControlledPanel.layoutHeight = FILL_PARENT;
1053         TextWidget treeItemLabel = new TextWidget("TREE_ITEM_DESC");
1054         treeItemLabel.layoutWidth = FILL_PARENT;
1055         treeItemLabel.layoutHeight = FILL_PARENT;
1056         treeItemLabel.alignment = Align.Center;
1057         treeItemLabel.text = "Sample text"d;
1058         treeControlledPanel.addChild(treeItemLabel);
1059         treeLayout.addChild(tree);
1060         treeLayout.addChild(new ResizerWidget());
1061         treeLayout.addChild(treeControlledPanel);
1062 
1063         tree.selectionChange = delegate(TreeItems source, TreeItem selectedItem, bool activated) {
1064             dstring label = "Selected item: "d ~ toUTF32(selectedItem.id) ~ (activated ? " selected + activated"d : " selected"d);
1065             treeItemLabel.text = label;
1066         };
1067 
1068         tree.items.selectItem(tree.items.child(0));
1069 
1070         tabs.addTab(treeLayout, "Tree"d);
1071         //==========================================================================
1072         // charts example
1073         SimpleBarChart barChart1 = new SimpleBarChart("barChart1","SimpleBarChart Example"d);
1074         barChart1.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1075         barChart1.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1076         barChart1.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1077         barChart1.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1078         //barChart1.layoutWidth = FILL_PARENT;
1079         //barChart1.layoutHeight = FILL_PARENT;
1080 
1081         SimpleBarChart barChart2 = new SimpleBarChart("barChart2","SimpleBarChart Example - long descriptions"d);
1082         barChart2.addBar(12.0, makeRGBA(255,0,0,0), "Red bar\n(12.0)"d);
1083         barChart2.addBar(24.0, makeRGBA(0,255,0,0), "Green bar\n(24.0)"d);
1084         barChart2.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar\n(5.0)"d);
1085         barChart2.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar\n(12.0)\nlong long long description added here"d);
1086 
1087         SimpleBarChart barChart3 = new SimpleBarChart("barChart3","SimpleBarChart Example with axis ratio 0.3"d);
1088         barChart3.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1089         barChart3.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1090         barChart3.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1091         barChart3.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1092         barChart3.axisRatio = 0.3;
1093 
1094         SimpleBarChart barChart4 = new SimpleBarChart("barChart4","SimpleBarChart Example with axis ratio 1.3"d);
1095         barChart4.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1096         barChart4.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1097         barChart4.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1098         barChart4.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1099         barChart4.axisRatio = 1.3;
1100 
1101         HorizontalLayout chartsLayout = new HorizontalLayout("CHARTS");
1102         chartsLayout.layoutWidth = FILL_PARENT;
1103         chartsLayout.layoutHeight = FILL_PARENT;
1104 
1105         VerticalLayout chartColumn1 = new VerticalLayout();
1106         VerticalLayout chartColumn2 = new VerticalLayout();
1107 
1108         chartColumn1.addChild(barChart1);
1109         chartColumn1.addChild(barChart2);
1110         chartsLayout.addChild(chartColumn1);
1111         chartColumn2.addChild(barChart3);
1112         chartColumn2.addChild(barChart4);
1113         chartsLayout.addChild(chartColumn2);
1114         tabs.addTab(chartsLayout, "Charts"d);
1115 
1116         //==========================================================================
1117 
1118         contentLayout.addChild(tabs);
1119         window.mainWidget = contentLayout;
1120 
1121         tabs.selectTab("controls");
1122     } else {
1123         window.mainWidget = (new Button()).text("sample button");
1124     }
1125 
1126     window.show();
1127 
1128     Log.i("HOME path: ", homePath);
1129     Log.i("APPDATA path: ", appDataPath(".dlangui"));
1130     Log.i("Root paths: ", getRootPaths);
1131 
1132     return Platform.instance.enterMessageLoop();
1133 }